#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
NSA5312 综合测试界面
Comprehensive Test Widget for NSA5312

基于excute.h文件的所有功能实现：
- 0x01: 获取版本信息
- 0x0A: 行控制
- 0x0B: 列控制  
- 0x10/0x11: I2C写/读
- 0x12/0x13: SPI写/读
- 0x14/0x15: SPI4写/读
- 0x1A/0x1B: OWI写/读
- 0x20: 8路电源控制
- 0x21: 5V/6.5V切换
- 0x22: COM接口切换OWI或AOUT
- 0x23: OWI校准模式
- 0x30: 单路ADC读取
- 0x40/0x41: 64通道ADC采集/发送
- 0x50/0x51/0x52: 64通道raw data采集/发送
- 0x53/0x54: I2C 64通道raw/cal数据采集
- 0x60/0x61/0x62: OWI 64通道cal数据采集/发送
- 0x63: NSA5312 64通道数据采集
"""

import sys
from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QTabWidget, 
                           QLabel, QLineEdit, QPushButton, QComboBox, QSpinBox, 
                           QGroupBox, QGridLayout, QTextEdit, QCheckBox,
                           QMessageBox, QProgressBar, QTableWidget, QTableWidgetItem,
                           QSplitter, QFrame, QScrollArea)
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QTimer
from PyQt5.QtGui import QFont, QColor

from serial_handler import NSA5312CommandHelper
from serial_protocol import CommandCode, StatusCode

class ComprehensiveTestWidget(QWidget):
    """NSA5312综合测试控件"""
    
    def __init__(self, command_helper: NSA5312CommandHelper):
        super().__init__()
        self.command_helper = command_helper
        self.init_ui()
    
    def init_ui(self):
        """初始化UI"""
        layout = QVBoxLayout()
        
        # 创建选项卡
        self.tab_widget = QTabWidget()
        
        # 基础控制选项卡
        self.basic_control_tab = self.create_basic_control_tab()
        self.tab_widget.addTab(self.basic_control_tab, "基础控制")
        
        # 通信接口选项卡
        self.interface_tab = self.create_interface_tab()
        self.tab_widget.addTab(self.interface_tab, "通信接口")
        
        # 数据采集选项卡
        self.data_collection_tab = self.create_data_collection_tab()
        self.tab_widget.addTab(self.data_collection_tab, "数据采集")
        
        # NSA5312特殊功能选项卡
        self.special_functions_tab = self.create_special_functions_tab()
        self.tab_widget.addTab(self.special_functions_tab, "NSA5312功能")
        
        layout.addWidget(self.tab_widget)
        self.setLayout(layout)
    
    def create_basic_control_tab(self):
        """创建基础控制选项卡"""
        widget = QWidget()
        layout = QVBoxLayout(widget)
        
        # 设备信息组
        info_group = QGroupBox("设备信息")
        info_layout = QGridLayout()
        
        # 0x01: 获取版本信息
        info_layout.addWidget(QLabel("固件版本:"), 0, 0)
        self.version_label = QLabel("未知")
        info_layout.addWidget(self.version_label, 0, 1)
        
        get_version_btn = QPushButton("获取版本 (0x01)")
        get_version_btn.clicked.connect(self.get_version)
        info_layout.addWidget(get_version_btn, 0, 2)
        
        info_group.setLayout(info_layout)
        layout.addWidget(info_group)
        
        # GPIO控制组
        gpio_group = QGroupBox("GPIO控制")
        gpio_layout = QGridLayout()
        
        # 0x0A: 行控制
        gpio_layout.addWidget(QLabel("行控制 (0x0A):"), 0, 0)
        self.row_value_spin = QSpinBox()
        self.row_value_spin.setRange(0, 255)
        self.row_value_spin.setDisplayIntegerBase(16)
        self.row_value_spin.setPrefix("0x")
        gpio_layout.addWidget(self.row_value_spin, 0, 1)
        
        row_btn = QPushButton("设置行")
        row_btn.clicked.connect(self.set_row_control)
        gpio_layout.addWidget(row_btn, 0, 2)
        
        # 0x0B: 列控制
        gpio_layout.addWidget(QLabel("列控制 (0x0B):"), 1, 0)
        self.col_value_spin = QSpinBox()
        self.col_value_spin.setRange(0, 255)
        self.col_value_spin.setDisplayIntegerBase(16)
        self.col_value_spin.setPrefix("0x")
        gpio_layout.addWidget(self.col_value_spin, 1, 1)
        
        col_btn = QPushButton("设置列")
        col_btn.clicked.connect(self.set_col_control)
        gpio_layout.addWidget(col_btn, 1, 2)
        
        gpio_group.setLayout(gpio_layout)
        layout.addWidget(gpio_group)
        
        # 电源和接口控制组
        power_group = QGroupBox("电源和接口控制")
        power_layout = QGridLayout()
        
        # 0x20: 8路电源控制
        power_layout.addWidget(QLabel("8路电源控制 (0x20):"), 0, 0)
        self.power_control_spin = QSpinBox()
        self.power_control_spin.setRange(0, 255)
        self.power_control_spin.setDisplayIntegerBase(16)
        self.power_control_spin.setPrefix("0x")
        power_layout.addWidget(self.power_control_spin, 0, 1)
        
        power_btn = QPushButton("设置电源")
        power_btn.clicked.connect(self.set_power_control)
        power_layout.addWidget(power_btn, 0, 2)
        
        # 0x21: 5V/6.5V切换
        power_layout.addWidget(QLabel("电压切换 (0x21):"), 1, 0)
        self.voltage_combo = QComboBox()
        self.voltage_combo.addItems(["5V (0x00)", "6.5V (0x01)"])
        power_layout.addWidget(self.voltage_combo, 1, 1)
        
        voltage_btn = QPushButton("切换电压")
        voltage_btn.clicked.connect(self.switch_voltage)
        power_layout.addWidget(voltage_btn, 1, 2)
        
        # 0x22: COM接口切换
        power_layout.addWidget(QLabel("接口切换 (0x22):"), 2, 0)
        self.interface_combo = QComboBox()
        self.interface_combo.addItems(["OWI (0x00)", "AOUT (0x01)"])
        power_layout.addWidget(self.interface_combo, 2, 1)
        
        interface_btn = QPushButton("切换接口")
        interface_btn.clicked.connect(self.switch_interface)
        power_layout.addWidget(interface_btn, 2, 2)
        
        power_group.setLayout(power_layout)
        layout.addWidget(power_group)
        
        layout.addStretch()
        return widget
    
    def create_interface_tab(self):
        """创建通信接口选项卡"""
        widget = QWidget()
        layout = QVBoxLayout(widget)
        
        # I2C接口组
        i2c_group = QGroupBox("I2C接口测试")
        i2c_layout = QGridLayout()
        
        # I2C参数
        i2c_layout.addWidget(QLabel("设备地址:"), 0, 0)
        self.i2c_dev_addr_spin = QSpinBox()
        self.i2c_dev_addr_spin.setRange(0, 127)
        self.i2c_dev_addr_spin.setValue(0x50)
        self.i2c_dev_addr_spin.setDisplayIntegerBase(16)
        self.i2c_dev_addr_spin.setPrefix("0x")
        i2c_layout.addWidget(self.i2c_dev_addr_spin, 0, 1)
        
        i2c_layout.addWidget(QLabel("寄存器地址:"), 0, 2)
        self.i2c_reg_addr_spin = QSpinBox()
        self.i2c_reg_addr_spin.setRange(0, 255)
        self.i2c_reg_addr_spin.setDisplayIntegerBase(16)
        self.i2c_reg_addr_spin.setPrefix("0x")
        i2c_layout.addWidget(self.i2c_reg_addr_spin, 0, 3)
        
        i2c_layout.addWidget(QLabel("数据长度:"), 1, 0)
        self.i2c_length_spin = QSpinBox()
        self.i2c_length_spin.setRange(1, 16)
        i2c_layout.addWidget(self.i2c_length_spin, 1, 1)
        
        i2c_layout.addWidget(QLabel("写入数据:"), 1, 2)
        self.i2c_write_data_edit = QLineEdit()
        self.i2c_write_data_edit.setPlaceholderText("如: AA BB CC (十六进制)")
        i2c_layout.addWidget(self.i2c_write_data_edit, 1, 3)
        
        # I2C按钮
        i2c_write_btn = QPushButton("I2C写 (0x10)")
        i2c_write_btn.clicked.connect(self.i2c_write_test)
        i2c_layout.addWidget(i2c_write_btn, 2, 0)
        
        i2c_read_btn = QPushButton("I2C读 (0x11)")
        i2c_read_btn.clicked.connect(self.i2c_read_test)
        i2c_layout.addWidget(i2c_read_btn, 2, 1)
        
        # I2C结果显示
        self.i2c_result_text = QTextEdit()
        self.i2c_result_text.setMaximumHeight(100)
        i2c_layout.addWidget(self.i2c_result_text, 3, 0, 1, 4)
        
        i2c_group.setLayout(i2c_layout)
        layout.addWidget(i2c_group)
        
        # SPI接口组
        spi_group = QGroupBox("SPI接口测试")
        spi_layout = QGridLayout()
        
        # SPI参数
        spi_layout.addWidget(QLabel("寄存器地址:"), 0, 0)
        self.spi_reg_addr_spin = QSpinBox()
        self.spi_reg_addr_spin.setRange(0, 255)
        self.spi_reg_addr_spin.setDisplayIntegerBase(16)
        self.spi_reg_addr_spin.setPrefix("0x")
        spi_layout.addWidget(self.spi_reg_addr_spin, 0, 1)
        
        spi_layout.addWidget(QLabel("数据长度:"), 0, 2)
        self.spi_length_spin = QSpinBox()
        self.spi_length_spin.setRange(1, 16)
        spi_layout.addWidget(self.spi_length_spin, 0, 3)
        
        spi_layout.addWidget(QLabel("写入数据:"), 1, 0)
        self.spi_write_data_edit = QLineEdit()
        self.spi_write_data_edit.setPlaceholderText("如: 55 AA FF (十六进制)")
        spi_layout.addWidget(self.spi_write_data_edit, 1, 1, 1, 3)
        
        # SPI按钮
        spi3_write_btn = QPushButton("SPI3写 (0x12)")
        spi3_write_btn.clicked.connect(lambda: self.spi_test(False, False))
        spi_layout.addWidget(spi3_write_btn, 2, 0)
        
        spi3_read_btn = QPushButton("SPI3读 (0x13)")
        spi3_read_btn.clicked.connect(lambda: self.spi_test(True, False))
        spi_layout.addWidget(spi3_read_btn, 2, 1)
        
        spi4_write_btn = QPushButton("SPI4写 (0x14)")
        spi4_write_btn.clicked.connect(lambda: self.spi_test(False, True))
        spi_layout.addWidget(spi4_write_btn, 2, 2)
        
        spi4_read_btn = QPushButton("SPI4读 (0x15)")
        spi4_read_btn.clicked.connect(lambda: self.spi_test(True, True))
        spi_layout.addWidget(spi4_read_btn, 2, 3)
        
        # SPI结果显示
        self.spi_result_text = QTextEdit()
        self.spi_result_text.setMaximumHeight(100)
        spi_layout.addWidget(self.spi_result_text, 3, 0, 1, 4)
        
        spi_group.setLayout(spi_layout)
        layout.addWidget(spi_group)
        
        # OWI接口组
        owi_group = QGroupBox("OWI接口测试")
        owi_layout = QGridLayout()
        
        # OWI参数
        owi_layout.addWidget(QLabel("寄存器地址:"), 0, 0)
        self.owi_reg_addr_spin = QSpinBox()
        self.owi_reg_addr_spin.setRange(0, 255)
        self.owi_reg_addr_spin.setDisplayIntegerBase(16)
        self.owi_reg_addr_spin.setPrefix("0x")
        owi_layout.addWidget(self.owi_reg_addr_spin, 0, 1)
        
        owi_layout.addWidget(QLabel("数据长度:"), 0, 2)
        self.owi_length_spin = QSpinBox()
        self.owi_length_spin.setRange(1, 16)
        owi_layout.addWidget(self.owi_length_spin, 0, 3)
        
        owi_layout.addWidget(QLabel("写入数据:"), 1, 0)
        self.owi_write_data_edit = QLineEdit()
        self.owi_write_data_edit.setPlaceholderText("如: 12 34 56 (十六进制)")
        owi_layout.addWidget(self.owi_write_data_edit, 1, 1, 1, 3)
        
        # OWI按钮
        owi_write_btn = QPushButton("OWI写 (0x1A)")
        owi_write_btn.clicked.connect(self.owi_write_test)
        owi_layout.addWidget(owi_write_btn, 2, 0)
        
        owi_read_btn = QPushButton("OWI读 (0x1B)")
        owi_read_btn.clicked.connect(self.owi_read_test)
        owi_layout.addWidget(owi_read_btn, 2, 1)
        
        # OWI结果显示
        self.owi_result_text = QTextEdit()
        self.owi_result_text.setMaximumHeight(100)
        owi_layout.addWidget(self.owi_result_text, 3, 0, 1, 4)
        
        owi_group.setLayout(owi_layout)
        layout.addWidget(owi_group)
        
        layout.addStretch()
        return widget
    
    def create_data_collection_tab(self):
        """创建数据采集选项卡"""
        widget = QWidget()
        layout = QVBoxLayout(widget)
        
        # 单路ADC采集组
        single_adc_group = QGroupBox("单路ADC采集")
        single_adc_layout = QGridLayout()
        
        # 0x30: 单路ADC读取
        single_adc_layout.addWidget(QLabel("ADC通道:"), 0, 0)
        self.adc_channel_spin = QSpinBox()
        self.adc_channel_spin.setRange(0, 63)
        single_adc_layout.addWidget(self.adc_channel_spin, 0, 1)
        
        adc_read_btn = QPushButton("读取ADC (0x30)")
        adc_read_btn.clicked.connect(self.read_single_adc)
        single_adc_layout.addWidget(adc_read_btn, 0, 2)
        
        self.adc_value_label = QLabel("0")
        single_adc_layout.addWidget(self.adc_value_label, 0, 3)
        
        single_adc_group.setLayout(single_adc_layout)
        layout.addWidget(single_adc_group)
        
        # 64通道数据采集组
        multi_adc_group = QGroupBox("64通道数据采集")
        multi_adc_layout = QGridLayout()
        
        # 0x40/0x41: 64通道ADC采集/发送
        adc_collect_btn = QPushButton("采集64通道ADC (0x40)")
        adc_collect_btn.clicked.connect(self.collect_64ch_adc)
        multi_adc_layout.addWidget(adc_collect_btn, 0, 0)
        
        adc_send_btn = QPushButton("发送64通道ADC (0x41)")
        adc_send_btn.clicked.connect(self.send_64ch_adc)
        multi_adc_layout.addWidget(adc_send_btn, 0, 1)
        
        # 0x50/0x51/0x52: raw data采集
        raw_collect_btn = QPushButton("采集64通道Raw (0x50)")
        raw_collect_btn.clicked.connect(self.collect_64ch_raw)
        multi_adc_layout.addWidget(raw_collect_btn, 1, 0)
        
        raw_pressure_btn = QPushButton("发送压力Raw (0x51)")
        raw_pressure_btn.clicked.connect(self.send_64ch_pressure_raw)
        multi_adc_layout.addWidget(raw_pressure_btn, 1, 1)
        
        raw_temp_btn = QPushButton("发送温度Raw (0x52)")
        raw_temp_btn.clicked.connect(self.send_64ch_temp_raw)
        multi_adc_layout.addWidget(raw_temp_btn, 1, 2)
        
        # I2C 64通道数据采集
        multi_adc_layout.addWidget(QLabel("I2C设备地址:"), 2, 0)
        self.i2c_64ch_addr_spin = QSpinBox()
        self.i2c_64ch_addr_spin.setRange(0, 127)
        self.i2c_64ch_addr_spin.setValue(0x50)
        self.i2c_64ch_addr_spin.setDisplayIntegerBase(16)
        self.i2c_64ch_addr_spin.setPrefix("0x")
        multi_adc_layout.addWidget(self.i2c_64ch_addr_spin, 2, 1)
        
        i2c_raw_btn = QPushButton("I2C采集Raw (0x53)")
        i2c_raw_btn.clicked.connect(self.collect_i2c_64ch_raw)
        multi_adc_layout.addWidget(i2c_raw_btn, 2, 2)
        
        i2c_cal_btn = QPushButton("I2C采集Cal (0x54)")
        i2c_cal_btn.clicked.connect(self.collect_i2c_64ch_cal)
        multi_adc_layout.addWidget(i2c_cal_btn, 2, 3)
        
        # OWI 64通道数据采集
        owi_cal_btn = QPushButton("OWI采集Cal (0x60)")
        owi_cal_btn.clicked.connect(self.collect_owi_64ch_cal)
        multi_adc_layout.addWidget(owi_cal_btn, 3, 0)
        
        owi_pressure_btn = QPushButton("OWI发送压力Cal (0x61)")
        owi_pressure_btn.clicked.connect(self.send_owi_64ch_pressure)
        multi_adc_layout.addWidget(owi_pressure_btn, 3, 1)
        
        owi_temp_btn = QPushButton("OWI发送温度Cal (0x62)")
        owi_temp_btn.clicked.connect(self.send_owi_64ch_temp)
        multi_adc_layout.addWidget(owi_temp_btn, 3, 2)
        
        # 进度条
        self.progress_bar = QProgressBar()
        multi_adc_layout.addWidget(self.progress_bar, 4, 0, 1, 4)
        
        multi_adc_group.setLayout(multi_adc_layout)
        layout.addWidget(multi_adc_group)
        
        # 数据显示区域
        data_display_group = QGroupBox("数据显示")
        data_display_layout = QVBoxLayout()
        
        self.data_display_text = QTextEdit()
        self.data_display_text.setMaximumHeight(200)
        self.data_display_text.setFont(QFont("Courier", 9))
        data_display_layout.addWidget(self.data_display_text)
        
        data_display_group.setLayout(data_display_layout)
        layout.addWidget(data_display_group)
        
        layout.addStretch()
        return widget
    
    def create_special_functions_tab(self):
        """创建NSA5312特殊功能选项卡"""
        widget = QWidget()
        layout = QVBoxLayout(widget)
        
        # OWI校准模式组
        owi_cal_group = QGroupBox("OWI校准模式")
        owi_cal_layout = QGridLayout()
        
        # 0x23: OWI校准模式
        owi_cal_layout.addWidget(QLabel("校准模式 (0x23):"), 0, 0)
        self.owi_cal_combo = QComboBox()
        self.owi_cal_combo.addItems(["关闭 (0x00)", "开启 (0x01)"])
        self.owi_cal_combo.setCurrentIndex(1)  # 默认开启
        owi_cal_layout.addWidget(self.owi_cal_combo, 0, 1)
        
        owi_cal_btn = QPushButton("执行OWI校准")
        owi_cal_btn.clicked.connect(self.owi_calibration_mode)
        owi_cal_layout.addWidget(owi_cal_btn, 0, 2)
        
        # 校准状态显示
        self.owi_cal_status_label = QLabel("未执行")
        owi_cal_layout.addWidget(self.owi_cal_status_label, 0, 3)
        
        owi_cal_group.setLayout(owi_cal_layout)
        layout.addWidget(owi_cal_group)
        
        # NSA5312 64通道采集组
        nsa5312_group = QGroupBox("NSA5312 64通道采集")
        nsa5312_layout = QGridLayout()
        
        # 0x63: NSA5312 64通道数据采集
        nsa5312_layout.addWidget(QLabel("超时时间 (0x63):"), 0, 0)
        self.nsa5312_timeout_spin = QSpinBox()
        self.nsa5312_timeout_spin.setRange(0, 255)
        self.nsa5312_timeout_spin.setValue(100)  # 默认100ms
        self.nsa5312_timeout_spin.setSuffix(" ms")
        nsa5312_layout.addWidget(self.nsa5312_timeout_spin, 0, 1)
        
        nsa5312_collect_btn = QPushButton("NSA5312采集64通道")
        nsa5312_collect_btn.clicked.connect(self.nsa5312_collect_64ch)
        nsa5312_layout.addWidget(nsa5312_collect_btn, 0, 2)
        
        # NSA5312采集状态
        self.nsa5312_status_label = QLabel("就绪")
        nsa5312_layout.addWidget(self.nsa5312_status_label, 0, 3)
        
        nsa5312_group.setLayout(nsa5312_layout)
        layout.addWidget(nsa5312_group)
        
        # 自定义命令组
        custom_group = QGroupBox("自定义命令测试")
        custom_layout = QGridLayout()
        
        custom_layout.addWidget(QLabel("命令代码:"), 0, 0)
        self.custom_cmd_spin = QSpinBox()
        self.custom_cmd_spin.setRange(0, 255)
        self.custom_cmd_spin.setDisplayIntegerBase(16)
        self.custom_cmd_spin.setPrefix("0x")
        custom_layout.addWidget(self.custom_cmd_spin, 0, 1)
        
        custom_layout.addWidget(QLabel("参数数据:"), 0, 2)
        self.custom_params_edit = QLineEdit()
        self.custom_params_edit.setPlaceholderText("如: 01 02 03 (十六进制)")
        custom_layout.addWidget(self.custom_params_edit, 0, 3)
        
        custom_send_btn = QPushButton("发送自定义命令")
        custom_send_btn.clicked.connect(self.send_custom_command)
        custom_layout.addWidget(custom_send_btn, 1, 0, 1, 2)
        
        # 自定义命令结果
        self.custom_result_text = QTextEdit()
        self.custom_result_text.setMaximumHeight(150)
        custom_layout.addWidget(self.custom_result_text, 2, 0, 1, 4)
        
        custom_group.setLayout(custom_layout)
        layout.addWidget(custom_group)
        
        layout.addStretch()
        return widget
    
    # ======= 实现函数 =======
    
    def get_version(self):
        """获取版本信息 (0x01)"""
        try:
            response = self.command_helper.get_version()
            if response.success:
                version = response.data[0] if response.data else 0
                self.version_label.setText(str(version))
                self.log_result(f"获取版本成功: {version}")
            else:
                self.show_error("获取版本失败", response.error_msg)
        except Exception as e:
            self.show_error("获取版本异常", str(e))
    
    def set_row_control(self):
        """设置行控制 (0x0A)"""
        try:
            value = self.row_value_spin.value()
            response = self.command_helper.control_gpio_row(0, value)  # channel参数在excute.h中未使用
            
            if response.success:
                self.log_result(f"设置行控制成功: 0x{value:02X}")
            else:
                self.show_error("设置行控制失败", response.error_msg)
        except Exception as e:
            self.show_error("设置行控制异常", str(e))
    
    def set_col_control(self):
        """设置列控制 (0x0B)"""
        try:
            value = self.col_value_spin.value()
            response = self.command_helper.control_gpio_col(0, value)  # channel参数在excute.h中未使用
            
            if response.success:
                self.log_result(f"设置列控制成功: 0x{value:02X}")
            else:
                self.show_error("设置列控制失败", response.error_msg)
        except Exception as e:
            self.show_error("设置列控制异常", str(e))
    
    def set_power_control(self):
        """设置8路电源控制 (0x20)"""
        try:
            value = self.power_control_spin.value()
            # 使用自定义命令发送0x20
            params = bytes([value])
            response = self.command_helper.send_custom_command(0x20, params)
            
            if response.success:
                self.log_result(f"设置8路电源成功: 0x{value:02X}")
            else:
                self.show_error("设置8路电源失败", response.error_msg)
        except Exception as e:
            self.show_error("设置8路电源异常", str(e))
    
    def switch_voltage(self):
        """切换电压 (0x21)"""
        try:
            index = self.voltage_combo.currentIndex()
            value = index  # 0=5V, 1=6.5V
            params = bytes([value])
            response = self.command_helper.send_custom_command(0x21, params)
            
            if response.success:
                voltage_text = "5V" if value == 0 else "6.5V"
                self.log_result(f"切换电压成功: {voltage_text}")
            else:
                self.show_error("切换电压失败", response.error_msg)
        except Exception as e:
            self.show_error("切换电压异常", str(e))
    
    def switch_interface(self):
        """切换接口 (0x22)"""
        try:
            index = self.interface_combo.currentIndex()
            value = index  # 0=OWI, 1=AOUT
            params = bytes([value])
            response = self.command_helper.send_custom_command(0x22, params)
            
            if response.success:
                interface_text = "OWI" if value == 0 else "AOUT"
                self.log_result(f"切换接口成功: {interface_text}")
            else:
                self.show_error("切换接口失败", response.error_msg)
        except Exception as e:
            self.show_error("切换接口异常", str(e))
    
    def parse_hex_data(self, hex_string):
        """解析十六进制字符串"""
        try:
            hex_values = hex_string.strip().split()
            return bytes([int(h, 16) for h in hex_values if h])
        except ValueError:
            raise ValueError("无效的十六进制格式")
    
    def i2c_write_test(self):
        """I2C写测试 (0x10)"""
        try:
            dev_addr = self.i2c_dev_addr_spin.value()
            reg_addr = self.i2c_reg_addr_spin.value()
            data_str = self.i2c_write_data_edit.text().strip()
            
            if not data_str:
                self.show_error("I2C写错误", "请输入要写入的数据")
                return
            
            data = self.parse_hex_data(data_str)
            response = self.command_helper.i2c_write(dev_addr, reg_addr, data)
            
            if response.success:
                self.i2c_result_text.append(f"I2C写成功: 设备=0x{dev_addr:02X}, 寄存器=0x{reg_addr:02X}, 数据={data_str}")
            else:
                self.i2c_result_text.append(f"I2C写失败: {response.error_msg}")
                
        except ValueError as e:
            self.show_error("I2C写错误", str(e))
        except Exception as e:
            self.show_error("I2C写异常", str(e))
    
    def i2c_read_test(self):
        """I2C读测试 (0x11)"""
        try:
            dev_addr = self.i2c_dev_addr_spin.value()
            reg_addr = self.i2c_reg_addr_spin.value()
            length = self.i2c_length_spin.value()
            
            response = self.command_helper.i2c_read(dev_addr, reg_addr, length)
            
            if response.success:
                data_str = " ".join(f"{b:02X}" for b in response.data)
                self.i2c_result_text.append(f"I2C读成功: 设备=0x{dev_addr:02X}, 寄存器=0x{reg_addr:02X}, 数据={data_str}")
            else:
                self.i2c_result_text.append(f"I2C读失败: {response.error_msg}")
                
        except Exception as e:
            self.show_error("I2C读异常", str(e))
    
    def spi_test(self, is_read, is_spi4):
        """SPI测试 (0x12/0x13/0x14/0x15)"""
        try:
            reg_addr = self.spi_reg_addr_spin.value()
            
            if is_read:
                length = self.spi_length_spin.value()
                response = self.command_helper.spi_read(length, is_spi4)
                op_name = "SPI4读" if is_spi4 else "SPI3读"
            else:
                data_str = self.spi_write_data_edit.text().strip()
                if not data_str:
                    self.show_error("SPI写错误", "请输入要写入的数据")
                    return
                
                data = self.parse_hex_data(data_str)
                response = self.command_helper.spi_write(data, is_spi4)
                op_name = "SPI4写" if is_spi4 else "SPI3写"
            
            if response.success:
                if is_read:
                    data_str = " ".join(f"{b:02X}" for b in response.data)
                    self.spi_result_text.append(f"{op_name}成功: 寄存器=0x{reg_addr:02X}, 数据={data_str}")
                else:
                    self.spi_result_text.append(f"{op_name}成功: 寄存器=0x{reg_addr:02X}")
            else:
                self.spi_result_text.append(f"{op_name}失败: {response.error_msg}")
                
        except ValueError as e:
            self.show_error("SPI测试错误", str(e))
        except Exception as e:
            self.show_error("SPI测试异常", str(e))
    
    def owi_write_test(self):
        """OWI写测试 (0x1A)"""
        try:
            reg_addr = self.owi_reg_addr_spin.value()
            data_str = self.owi_write_data_edit.text().strip()
            
            if not data_str:
                self.show_error("OWI写错误", "请输入要写入的数据")
                return
            
            data = self.parse_hex_data(data_str)
            response = self.command_helper.owi_write(data)
            
            if response.success:
                self.owi_result_text.append(f"OWI写成功: 寄存器=0x{reg_addr:02X}, 数据={data_str}")
            else:
                self.owi_result_text.append(f"OWI写失败: {response.error_msg}")
                
        except ValueError as e:
            self.show_error("OWI写错误", str(e))
        except Exception as e:
            self.show_error("OWI写异常", str(e))
    
    def owi_read_test(self):
        """OWI读测试 (0x1B)"""
        try:
            reg_addr = self.owi_reg_addr_spin.value()
            length = self.owi_length_spin.value()
            
            response = self.command_helper.owi_read(length)
            
            if response.success:
                data_str = " ".join(f"{b:02X}" for b in response.data)
                self.owi_result_text.append(f"OWI读成功: 寄存器=0x{reg_addr:02X}, 数据={data_str}")
            else:
                self.owi_result_text.append(f"OWI读失败: {response.error_msg}")
                
        except Exception as e:
            self.show_error("OWI读异常", str(e))
    
    def read_single_adc(self):
        """读取单路ADC (0x30)"""
        try:
            channel = self.adc_channel_spin.value()
            response = self.command_helper.read_adc_channel(channel)
            
            if response.success and response.data:
                adc_value = int.from_bytes(response.data[:2], byteorder='big')
                self.adc_value_label.setText(str(adc_value))
                self.log_result(f"ADC通道{channel}读取成功: {adc_value}")
            else:
                self.show_error("读取ADC失败", response.error_msg)
        except Exception as e:
            self.show_error("读取ADC异常", str(e))
    
    def collect_64ch_adc(self):
        """采集64通道ADC (0x40)"""
        try:
            self.progress_bar.setValue(0)
            response = self.command_helper.collect_64ch_data(CommandCode.ADC_64CH_COLLECT)
            
            if response.success:
                self.progress_bar.setValue(100)
                self.log_result("64通道ADC采集完成")
            else:
                self.show_error("64通道ADC采集失败", response.error_msg)
        except Exception as e:
            self.show_error("64通道ADC采集异常", str(e))
    
    def send_64ch_adc(self):
        """发送64通道ADC数据 (0x41)"""
        try:
            response = self.command_helper.collect_64ch_data(CommandCode.ADC_64CH_SEND)
            
            if response.success:
                self.display_data_result("64通道ADC数据", response.data)
            else:
                self.show_error("发送64通道ADC数据失败", response.error_msg)
        except Exception as e:
            self.show_error("发送64通道ADC数据异常", str(e))
    
    def collect_64ch_raw(self):
        """采集64通道Raw数据 (0x50)"""
        try:
            self.progress_bar.setValue(0)
            response = self.command_helper.collect_64ch_data(CommandCode.RAW_64CH_COLLECT)
            
            if response.success:
                self.progress_bar.setValue(100)
                self.log_result("64通道Raw数据采集完成")
            else:
                self.show_error("64通道Raw数据采集失败", response.error_msg)
        except Exception as e:
            self.show_error("64通道Raw数据采集异常", str(e))
    
    def send_64ch_pressure_raw(self):
        """发送64通道压力Raw数据 (0x51)"""
        try:
            response = self.command_helper.collect_64ch_data(CommandCode.RAW_64CH_PRESSURE_SEND)
            
            if response.success:
                self.display_data_result("64通道压力Raw数据", response.data)
            else:
                self.show_error("发送64通道压力Raw数据失败", response.error_msg)
        except Exception as e:
            self.show_error("发送64通道压力Raw数据异常", str(e))
    
    def send_64ch_temp_raw(self):
        """发送64通道温度Raw数据 (0x52)"""
        try:
            response = self.command_helper.collect_64ch_data(CommandCode.RAW_64CH_TEMP_SEND)
            
            if response.success:
                self.display_data_result("64通道温度Raw数据", response.data)
            else:
                self.show_error("发送64通道温度Raw数据失败", response.error_msg)
        except Exception as e:
            self.show_error("发送64通道温度Raw数据异常", str(e))
    
    def collect_i2c_64ch_raw(self):
        """I2C采集64通道Raw数据 (0x53)"""
        try:
            dev_addr = self.i2c_64ch_addr_spin.value()
            params = bytes([dev_addr])
            response = self.command_helper.send_custom_command(0x53, params)
            
            if response.success:
                self.log_result(f"I2C 64通道Raw数据采集完成 (设备: 0x{dev_addr:02X})")
            else:
                self.show_error("I2C 64通道Raw数据采集失败", response.error_msg)
        except Exception as e:
            self.show_error("I2C 64通道Raw数据采集异常", str(e))
    
    def collect_i2c_64ch_cal(self):
        """I2C采集64通道Cal数据 (0x54)"""
        try:
            dev_addr = self.i2c_64ch_addr_spin.value()
            params = bytes([dev_addr])
            response = self.command_helper.send_custom_command(0x54, params)
            
            if response.success:
                self.log_result(f"I2C 64通道Cal数据采集完成 (设备: 0x{dev_addr:02X})")
            else:
                self.show_error("I2C 64通道Cal数据采集失败", response.error_msg)
        except Exception as e:
            self.show_error("I2C 64通道Cal数据采集异常", str(e))
    
    def collect_owi_64ch_cal(self):
        """OWI采集64通道Cal数据 (0x60)"""
        try:
            response = self.command_helper.collect_64ch_data(CommandCode.OWI_64CH_CAL_COLLECT)
            
            if response.success:
                self.log_result("OWI 64通道Cal数据采集完成")
            else:
                self.show_error("OWI 64通道Cal数据采集失败", response.error_msg)
        except Exception as e:
            self.show_error("OWI 64通道Cal数据采集异常", str(e))
    
    def send_owi_64ch_pressure(self):
        """OWI发送64通道压力Cal数据 (0x61)"""
        try:
            response = self.command_helper.collect_64ch_data(CommandCode.OWI_64CH_PRESSURE_SEND)
            
            if response.success:
                self.display_data_result("OWI 64通道压力Cal数据", response.data)
            else:
                self.show_error("OWI发送64通道压力Cal数据失败", response.error_msg)
        except Exception as e:
            self.show_error("OWI发送64通道压力Cal数据异常", str(e))
    
    def send_owi_64ch_temp(self):
        """OWI发送64通道温度Cal数据 (0x62)"""
        try:
            response = self.command_helper.collect_64ch_data(CommandCode.OWI_64CH_TEMP_SEND)
            
            if response.success:
                self.display_data_result("OWI 64通道温度Cal数据", response.data)
            else:
                self.show_error("OWI发送64通道温度Cal数据失败", response.error_msg)
        except Exception as e:
            self.show_error("OWI发送64通道温度Cal数据异常", str(e))
    
    def owi_calibration_mode(self):
        """OWI校准模式 (0x23)"""
        try:
            mode = self.owi_cal_combo.currentIndex()  # 0=关闭, 1=开启
            params = bytes([mode])
            response = self.command_helper.send_custom_command(0x23, params)
            
            if response.success:
                mode_text = "开启" if mode == 1 else "关闭"
                self.owi_cal_status_label.setText(f"校准模式: {mode_text}")
                self.log_result(f"OWI校准模式{mode_text}成功")
            else:
                self.owi_cal_status_label.setText("执行失败")
                self.show_error("OWI校准模式失败", response.error_msg)
        except Exception as e:
            self.show_error("OWI校准模式异常", str(e))
    
    def nsa5312_collect_64ch(self):
        """NSA5312 64通道数据采集 (0x63)"""
        try:
            timeout = self.nsa5312_timeout_spin.value()
            params = bytes([timeout])
            response = self.command_helper.send_custom_command(0x63, params)
            
            if response.success:
                self.nsa5312_status_label.setText("采集完成")
                self.log_result(f"NSA5312 64通道数据采集完成 (超时: {timeout}ms)")
            else:
                self.nsa5312_status_label.setText("采集失败")
                self.show_error("NSA5312 64通道数据采集失败", response.error_msg)
        except Exception as e:
            self.show_error("NSA5312 64通道数据采集异常", str(e))
    
    def send_custom_command(self):
        """发送自定义命令"""
        try:
            cmd = self.custom_cmd_spin.value()
            params_str = self.custom_params_edit.text().strip()
            
            if params_str:
                params = self.parse_hex_data(params_str)
            else:
                params = b''
            
            response = self.command_helper.send_custom_command(cmd, params)
            
            if response.success:
                data_str = " ".join(f"{b:02X}" for b in response.data) if response.data else "无数据"
                self.custom_result_text.append(f"自定义命令 0x{cmd:02X} 成功:")
                self.custom_result_text.append(f"  参数: {params_str if params_str else '无'}")
                self.custom_result_text.append(f"  响应: {data_str}")
                self.custom_result_text.append("")
            else:
                self.custom_result_text.append(f"自定义命令 0x{cmd:02X} 失败: {response.error_msg}")
                
        except ValueError as e:
            self.show_error("自定义命令错误", str(e))
        except Exception as e:
            self.show_error("自定义命令异常", str(e))
    
    # ======= 辅助函数 =======
    
    def show_error(self, title, message):
        """显示错误消息"""
        QMessageBox.warning(self, title, message)
    
    def log_result(self, message):
        """记录结果到数据显示区域"""
        self.data_display_text.append(f"[{self.get_timestamp()}] {message}")
        # 自动滚动到底部
        cursor = self.data_display_text.textCursor()
        cursor.movePosition(cursor.End)
        self.data_display_text.setTextCursor(cursor)
    
    def display_data_result(self, title, data):
        """显示数据结果"""
        if data:
            data_str = " ".join(f"{b:02X}" for b in data[:32])  # 只显示前32字节
            if len(data) > 32:
                data_str += f" ... (共{len(data)}字节)"
            self.log_result(f"{title}: {data_str}")
        else:
            self.log_result(f"{title}: 无数据")
    
    def get_timestamp(self):
        """获取时间戳"""
        from datetime import datetime
        return datetime.now().strftime("%H:%M:%S")